﻿// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.IO;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using Azure.Core.TestFramework;
using NUnit.Framework;

namespace Azure.AI.DocumentIntelligence.Tests
{
    public class DocumentClassifierAdministrationMockTests : ClientTestBase
    {
        public DocumentClassifierAdministrationMockTests(bool isAsync)
            : base(isAsync)
        {
        }

        [Test]
        [TestCase(true)]
        [TestCase(false)]
        public async Task CopyClassifierTo(bool isAsync)
        {
            using var postResponse = new MockResponse(202);

            postResponse.AddHeader("operation-location", "https://fakeResource.azure.com/documentIntelligence/operations/0123456789ABCDEF?api-version=2024-07-31-preview");

            using var getResponseRunning = new MockResponse(200);
            using var getResponseRunningBody = new MemoryStream(Encoding.UTF8.GetBytes("""
                {
                    "status": "running",
                    "percentCompleted": 67,
                    "createdDateTime": "2021-09-24T13:00:46Z",
                    "lastUpdatedDateTime": "2021-09-24T13:00:49Z"
                }
                """));

            getResponseRunning.ContentStream = getResponseRunningBody;

            using var getResponseCompleted = new MockResponse(200);
            using var getResponseCompletedBody = new MemoryStream(Encoding.UTF8.GetBytes("""
                {
                    "status": "succeeded",
                    "percentCompleted": 100,
                    "createdDateTime": "2021-09-24T13:00:46Z",
                    "lastUpdatedDateTime": "2021-09-24T13:00:55Z",
                    "result": {
                        "classifierId": "new_classifier_id",
                        "createdDateTime": "2024-01-01T00:00:00Z",
                        "expirationDateTime": "2024-02-01T00:00:00Z",
                        "apiVersion": "2024-07-31-preview",
                        "description": "This classifier was generated by a .NET test."
                    }
                }
                """));

            getResponseCompleted.ContentStream = getResponseCompletedBody;

            var mockTransport = new InterceptorMockTransport(new[] { postResponse, getResponseRunning, getResponseCompleted });
            var options = new DocumentIntelligenceClientOptions() { Transport = mockTransport };
            var client = CreateNonInstrumentedClient(options);

            ClassifierCopyAuthorization copyAuthorization = new ClassifierCopyAuthorization()
            {
                TargetClassifierId = "target_classifier_id",
                TargetClassifierLocation = new Uri("https://fake_classifier_location.com/"),
                TargetResourceId = "resource_id",
                TargetResourceRegion = "resource_region",
                AccessToken = "token",
                ExpiresOn = new DateTimeOffset(2024, 9, 24, 0, 0, 0, TimeSpan.Zero)
            };

            var operation = isAsync
                ? await client.CopyClassifierToAsync(WaitUntil.Completed, "new_classifier_id", copyAuthorization)
                : client.CopyClassifierTo(WaitUntil.Completed, "new_classifier_id", copyAuthorization);

            // Validate the request.

            var postRequestBody = mockTransport.FirstRequestBody;
            var postRequestJson = JsonDocument.Parse(postRequestBody);

            var targetClassifierIdElement = postRequestJson.RootElement.GetProperty("targetClassifierId");
            var targetClassifierLocationElement = postRequestJson.RootElement.GetProperty("targetClassifierLocation");
            var targetResourceIdIdElement = postRequestJson.RootElement.GetProperty("targetResourceId");
            var targetResourceRegionIdElement = postRequestJson.RootElement.GetProperty("targetResourceRegion");
            var targetAccessTokenElement = postRequestJson.RootElement.GetProperty("accessToken");
            var targetExpirationDateTimeElement = postRequestJson.RootElement.GetProperty("expirationDateTime");

            Assert.That(targetClassifierIdElement.ToString(), Is.EqualTo("target_classifier_id"));
            Assert.That(targetClassifierLocationElement.ToString(), Is.EqualTo("https://fake_classifier_location.com/"));
            Assert.That(targetResourceIdIdElement.ToString(), Is.EqualTo("resource_id"));
            Assert.That(targetResourceRegionIdElement.ToString(), Is.EqualTo("resource_region"));
            Assert.That(targetAccessTokenElement.ToString(), Is.EqualTo("token"));
            Assert.That(targetExpirationDateTimeElement.ToString(), Is.EqualTo("2024-09-24T00:00:00.0000000Z"));

            // Validate the response.

            Assert.That(operation.HasValue);
            Assert.That(operation.HasCompleted);

            var result = operation.Value;

            DateTimeOffset expectedCreatedOn = new DateTimeOffset(2024, 1, 1, 0, 0, 0, TimeSpan.Zero);
            DateTimeOffset expectedExpiresOn = new DateTimeOffset(2024, 2, 1, 0, 0, 0, TimeSpan.Zero);

            Assert.That(result.ClassifierId, Is.EqualTo("new_classifier_id"));
            Assert.That(result.CreatedOn, Is.EqualTo(expectedCreatedOn));
            Assert.That(result.ExpiresOn, Is.EqualTo(expectedExpiresOn));
            Assert.That(result.ApiVersion, Is.EqualTo("2024-07-31-preview"));
            Assert.That(result.Description, Is.EqualTo("This classifier was generated by a .NET test."));
        }

        [Test]
        [TestCase(true)]
        [TestCase(false)]
        public async Task AuthorizeClassifierCopy(bool isAsync)
        {
            using var mockResponse = new MockResponse(200);
            using var mockResponseBody = new MemoryStream(Encoding.UTF8.GetBytes("""
                {
                    "targetClassifierId": "target_classifier_id",
                    "targetClassifierLocation": "https://fake_classifier_location.com",
                    "targetResourceId": "resource_id",
                    "targetResourceRegion": "resource_region",
                    "accessToken": "token",
                    "expirationDateTime": "2024-09-24T00:00:00Z"
                }
                """));

            mockResponse.ContentStream = mockResponseBody;

            var mockTransport = new InterceptorMockTransport(new[] { mockResponse });
            var clientOptions = new DocumentIntelligenceClientOptions() { Transport = mockTransport };
            var client = CreateNonInstrumentedClient(clientOptions);

            var options = new AuthorizeClassifierCopyOptions("classifier_id");

            ClassifierCopyAuthorization copyAuthorization = isAsync
                ? await client.AuthorizeClassifierCopyAsync(options)
                : client.AuthorizeClassifierCopy(options);

            // Validate the request.

            var postRequestBody = mockTransport.FirstRequestBody;
            var postRequestJson = JsonDocument.Parse(postRequestBody);

            var classifierIdElement = postRequestJson.RootElement.GetProperty("classifierId");

            Assert.That(classifierIdElement.ToString(), Is.EqualTo("classifier_id"));

            // Validate the response.

            DateTimeOffset expectedTime = new DateTimeOffset(2024, 9, 24, 0, 0, 0, TimeSpan.Zero);

            Assert.That(copyAuthorization.TargetClassifierId, Is.EqualTo("target_classifier_id"));
            Assert.That(copyAuthorization.TargetClassifierLocation.AbsoluteUri, Is.EqualTo("https://fake_classifier_location.com/"));
            Assert.That(copyAuthorization.TargetResourceId, Is.EqualTo("resource_id"));
            Assert.That(copyAuthorization.TargetResourceRegion, Is.EqualTo("resource_region"));
            Assert.That(copyAuthorization.AccessToken, Is.EqualTo("token"));
            Assert.That(copyAuthorization.ExpiresOn, Is.EqualTo(expectedTime));
        }

        private DocumentIntelligenceAdministrationClient CreateNonInstrumentedClient(DocumentIntelligenceClientOptions options)
        {
            var fakeEndpoint = new Uri("http://localhost");
            var fakeCredential = new AzureKeyCredential("fakeKey");

            return new DocumentIntelligenceAdministrationClient(fakeEndpoint, fakeCredential, options);
        }
    }
}
